#pragma once
#include "shader.h"
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <assert.h>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> 

#include "ilcontainer.h"
#include "planar_mesh.h"
#include "fbo.h"

using namespace std;

enum Mode 
{
	ORANGE_BEAUTY,
	BOTTLE_BEAUTY,
	PICTURE_FRAME_BEAUTY,
	STILL_LIFE
};

enum Wallpaper
{
	WALLPAPER_1,
	WALLPAPER_2,
	WALLPAPER_3, 
	DISPLACEMENT_MAP
};

struct WindowStruct
{
	glm::ivec2 grid_size1;
	glm::ivec2 grid_size2;
	float (* function1)(float);
	float (* function2)(float);
	bool open;
};

class Window
{
public:
	FrameBufferObject fbo;
	glm::vec2 sourcePosition;
	glm::vec2 destinationPosition;
	GLsizei width;
	GLsizei height;
	GLuint window_handle;
	GLint period;
	GLsizei x;
	GLsizei y;
	enum Mode mode;
	ADSShader * shader;
	DMShader * dm_shader;
	enum Wallpaper wallpaper;

	Window(GLsizei w, GLsizei h, ADSShader * shader, DMShader * dm_shader);
	void DrawScene();
	void SetupShader(glm::mat4 projection_matrix, 
		glm::mat4 modelview_matrix, glm::mat3 normal_matrix, glm::mat4 mvp_matrix);
	void SetupDMShader( glm::mat4 projection_matrix, 
		glm::mat4 modelview_matrix, glm::mat3 normal_matrix, glm::mat4 mvp_matrix);
	void SetupHandles(GLuint * array_handle, PlanarMesh * mesh);
	void DrawOrange();
	void InitializeMatrices();
	void DrawNormals(PlanarMesh * planarMesh);
	void DrawBottle();
	void DrawBackGround();
	void DrawCube(glm::mat4 modelview_matrix);
	void DrawFace(glm::mat4 modelview_matrix);
	void UpdateSource(glm::vec2 position);
	void UpdateDestination(glm::vec2 position);
	void DrawToFrameBuffer(Wallpaper wallpaper, glm::mat4 modelview_matrix);
	void DrawDM();
	void SwitchWallpaper();
	void SetTexture();
	void CyclecurrentColorAttachment();


	
	//virtual void KeyboardFunc(unsigned char c, int x, int y) = 0;
	//virtual void TimerFunc(int value) = 0;
	bool PostGLInitialize(void * data, Mode mode);
	//virtual void TakeDown() = 0;

	void ApplyCustomization(float (* function)(float), PlanarMesh * planarMesh);

	void Axes();

	PlanarMesh * planar_mesh1;
	PlanarMesh * planar_mesh2;
	PlanarMesh * cube_mesh;
	ADSShader ADS_shader;
	DMShader DM_shader; 


	GLuint vertex_coordinate_handle;
	GLuint normal_value_handle;
	GLuint texture_coordinate_handle;
	GLuint vertex_array_handle;
	GLuint planar_mesh_1_handle;
	GLuint planar_mesh_2_handle;
	GLuint cube_vertex_array_handle;

	ILContainer normal_map_container;
	ILContainer wallpaper1_container;
	ILContainer wallpaper2_container;
	ILContainer wallpaper3_container;
	ILContainer buckyTex_container;
	ILContainer wood1_container;

	bool wireframe;
	bool draw_normals;
	bool force_open;
	bool do_normal_mapping;
	bool do_texture_mapping;
	bool do_displacement_mapping;
	bool destinationSet;
	bool drewDestinationSet;

	//Did not add destructor

	private:

	float (*function)(float);

	void InitializeGLHandles()
	{
		this->vertex_array_handle = BAD_GL_VALUE;
		this->vertex_coordinate_handle = BAD_GL_VALUE;
		this->texture_coordinate_handle = BAD_GL_VALUE;
		this->normal_value_handle = BAD_GL_VALUE;
	}

};
